#!/usr/bin/env python
# -*- coding: utf-8 -*-
__title__ = ''
__author__ = 'HaiFeng'
__mtime__ = ''

from PyQt5.QtCore import QAbstractTableModel, QModelIndex, QVariant, Qt, pyqtSignal
import sys


class HaifengTableModel(QAbstractTableModel):
    dataChanged = pyqtSignal(QModelIndex, QModelIndex)

    def __init__(self, type_of_struct: type):
        super(HaifengTableModel, self).__init__()
        self.dirty = False
        self.type = type_of_struct
        self.objects = []

    def sortByName(self):
        self.beginResetModel()
        self.objects = sorted(self.objects)
        self.endResetModel()

    def flags(self, index):
        if not index.isValid():
            return Qt.ItemIsEnabled
        return Qt.ItemFlags(
            QAbstractTableModel.flags(self, index) |
            Qt.ItemIsEditable)

    def data(self, index, role=Qt.DisplayRole):
        if (not index.isValid() or not (0 <= index.row() < len(self.objects))):
            return QVariant()
        obj = self.objects[index.row()]
        if obj is None:
            return
        column = index.column()
        if role == Qt.DisplayRole:
            if column < len(obj.__dict__.items()):
                val = obj.__dict__[list(obj.__dict__)[column]]
                if type(val) is float:
                    if val == sys.float_info.max:
                        val = 0.0
                    val = '{0:.2f}'.format(val)
                return val
            return obj
        if role == Qt.TextAlignmentRole:
            return QVariant(int(Qt.AlignLeft | Qt.AlignVCenter))

        return QVariant()

    def rowCount(self, index=QModelIndex()):
        return len(self.objects)

    def columnCount(self, index=QModelIndex()):
        return len(self.type().__dict__)

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role == Qt.TextAlignmentRole:
            if orientation == Qt.Horizontal:
                return QVariant(int(Qt.AlignLeft | Qt.AlignVCenter))
            return QVariant(int(Qt.AlignRight | Qt.AlignVCenter))
        if role != Qt.DisplayRole:
            return QVariant()
        if orientation == Qt.Horizontal:
            return QVariant(list(self.type().__dict__)[section])
        return QVariant(int(section + 1))

    # 此事件不会被触发
    def setData(self, index, value, role=Qt.EditRole):
        if index.isValid() and 0 <= index.row() < len(self.objects):
            # self.beginResetModel()
            obj = self.objects[index.row()]
            column = index.column()
            key = list(obj.__dict__)[column]
            vol = obj.__dict__[key]
            if type(vol) is str:
                setattr(obj, key, str(value))
            elif type(vol) is float:
                setattr(obj, key, float(value))
            elif type(vol) is int:
                setattr(obj, key, int(value))
            else:
                setattr(obj, key, value)
            self.dirty = True
            self.dataChanged[QModelIndex, QModelIndex].emit(index, index)
            # self.endResetModel()
            return True
        return False

    def insertRows(self, position, rows=1, index=QModelIndex()):
        self.beginInsertRows(QModelIndex(), position, position + rows - 1)
        for row in range(rows):
            self.objects.insert(position + row, self.type())
        self.endInsertRows()
        self.dirty = True
        return True

    def removeRows(self, position, rows=1, index=QModelIndex()):
        self.beginRemoveRows(QModelIndex(), position, position + rows - 1)
        self.objects = (self.objects[:position] + self.objects[position + rows:])
        self.endRemoveRows()
        self.dirty = True
        return True
